#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <map>
#include <stdlib.h>
#include <lineages.h>
#include <algorithm>
#include <stdio.h>
#include <sstream>
#include <math.h>
#include <time.h>
#include <shared.h>

using namespace std;

int fitnessType;
int robustType;
int disturbType;

double baseDelRate = 1.0;

void usage();

int main(int argc, char *argv[])
{
	if(argc != 7)
	{
		usage();
		exit(255);
	}
    string realLineagesFile = argv[1];
    fitnessType = atoi(argv[2]);
    robustType = atoi(argv[3]);
    disturbType = atoi(argv[4]);
    string resFile = argv[5];
    int randSeed = atoi(argv[6]);
    srand(randSeed);

    double realComplexity,realRobustness;
    vector<int> termTypes;
    vector<string> termLineages;
    vector<vector<string> > lineagesPool;
    vector<vector<int> > typesPool;
    vector<double> allRobust;

    loadRealLineages(realLineagesFile,termTypes,termLineages);
    Lineages realLin(termTypes,termLineages);

    realLin.getDepthStat();
    realComplexity = realLin.complexity();
    realLin.ruleDeletionRate = baseDelRate / (realLin.termTypes.size() - 1);
    // Here the denominator is (realLin.termTypes.size() - 1)
    // This is correct!! See explanations below, when calculating this metric for the simulated trees.
    if(disturbType == 1) {
		realRobustness = realLin.robustness1_Detail(robustType,allRobust);
    } else if (disturbType == 22) {
    	realRobustness = realLin.robustness2Sample_Detail(robustType,allRobust);
    }

    ofstream ofs;
    ofs.open(resFile.c_str());

    ofs << "Parameters: FitnessType(" << fitnessType;
    ofs << ") ; RobustType(" << robustType << ")";
    ofs << endl;

    ofs << "Lineage Name\tComplexity\tRobustness\tMax depth\tMean depth\tS.D. depth\tfitness" << endl;
    ofs << realLineagesFile << "\t" << realComplexity << "\t" << realRobustness << "\t" << realLin.depthMax << "\t";
    ofs << realLin.depthMean << "\t" << realLin.depthSD << "\t" << fitness(fitnessType,realRobustness,realComplexity) << endl;
	for(unsigned int i=0;i<allRobust.size();i++) {
		ofs << i << "\t" << realComplexity << "\t" << allRobust[i] << "\t" << realLin.depthMax << "\t";
		ofs << realLin.depthMean << "\t" << realLin.depthSD << "\t" << fitness(fitnessType,realRobustness,realComplexity) << endl;
	}
	ofs.close();

    return 0;
}

void usage()
{
	cerr << "List the fitness upon each individual perturbation event." << endl;
	cerr << "Usage: fitPerEvent lin fit robust disturb res seed" << endl;
	cerr << "Parameters (all are needed) :"<< endl;
	cerr << "  lin      : name of the lineage file, the name must contain one of these strings" << endl;
	cerr << "             \"fun\".  C. elegans functional classification" << endl;
	cerr << "             \"pma\".  P. marina functional classification" << endl;
	cerr << "             \"hro\".  H. roretzi functional classification" << endl;
	cerr << "  fit      : fitness type. 0-4" << endl;
	cerr << "             0.  robustness" << endl;
	cerr << "             1.  (1-complexity)" << endl;
	cerr << "             2.  robustness/complexity" << endl;
	cerr << "             3.  robustness^5/complexity" << endl;
	cerr << "             4.  robustness^100/complexity" << endl;
	cerr << " robust    : type of robustness. 1-3" << endl;
	cerr << "             1.  product of fractional survival in each type" << endl;
	cerr << "             2.  fractional survival of all non-apoptotic cells" << endl;
	cerr << "             3.  weighted product of fractional survival in each type" << endl;
	cerr << " disturb   : type of disturbance. 1 or 22" << endl;
	cerr << "             1.  a single necrosis among non-root cells" << endl;
	cerr << "             22.  program failure at the rate of 1/N_i, N_i is the number of internal nodes" << endl;
	cerr << " res       : file name for output" << endl;
	cerr << " seed      : seed for randomization" << endl;
	cerr << " " << endl;
	return;
}
